package com.sparrow.bean;

import com.alibaba.fastjson.JSONObject;
import com.sparrow.exception.ChannelNotExistException;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * Created by wancheng on 2019/4/13.
 */
public class RoomManage {

    private static class LazyHolder {
        private static final RoomManage OUR_INSTANCE = new RoomManage();
    }

    public static RoomManage getInstance() {
        return LazyHolder.OUR_INSTANCE;
    }

    private ConcurrentHashMap<Integer, Room> rooms = new ConcurrentHashMap<Integer, Room>(8);

    private ConcurrentHashMap<ChannelId, Member> members = new ConcurrentHashMap<ChannelId, Member>(8);

    /**
     * 创建会话房间
     * @param lessonId
     * @return
     */
    public Room initRoom(Integer lessonId) {
        Room room = rooms.get(lessonId);
        if (room != null) {
            return room;
        }
        room = new Room();
        room.setRoomId(lessonId);
        rooms.put(lessonId, room);
        return room;
    }

    /**
     * 成员注册
     * @param message
     * @param incoming
     */
    public void register(Message message,Channel incoming) {
        Member member = new Member(message.getLessonId(),incoming.id(),message.getRole(),message.getName(),message.getAccount());
        Room room = initRoom(message.getLessonId());
        List<Member> roomMembers = room.getMembers();
        if (roomMembers == null) {
            roomMembers = new ArrayList<>();
        }
        roomMembers.add(member);
        room.setMembers(roomMembers);
        members.put(member.getChannelId(), member);
        message.setMsg("注册成功");
        message.setCode(SocketStatus.SOCKET_SUCCESS);
        incoming.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSON(message).toString()));
    }

    /**
     * 移除
     * @param lessonId
     */
    public void destroy(Integer lessonId) {
        Room room = rooms.get(lessonId);
        List<Member> roomMembers = room.getMembers();
        roomMembers.stream().map(Member::getChannelId).forEach(channelId -> members.remove(channelId));
        rooms.remove(lessonId);
    }

    /**
     * 获取发送消息的目标群体
     *
     * @param channel
     * @throws Exception
     */
    public List<Member> targetGroups(Channel channel) throws Exception {
        Member member = members.get(channel.id());
        if (member == null) {
            throw new ChannelNotExistException();
        }
        Room room = rooms.get(member.getRoomId());
        Map<Role, List<Member>> memberMap = room.getMembers().stream().collect(Collectors.groupingBy(Member::getRole));
        if (Role.STUDENT.equals(member.getRole())) {
            return memberMap.get(Role.TEACHER);
        } else {
            return memberMap.get(Role.STUDENT);
        }
    }

    /**
     * 发送命令发送消息
     * @param allGroups
     * @param channel
     * @param message
     * @throws Exception
     */
    public void send(ChannelGroup allGroups,Channel channel,Message message) throws Exception {
        List<Member> targetGroups = targetGroups(channel);
        this.send(allGroups,targetGroups,message);
    }

    public void send(ChannelGroup allGroups,List<Member> targetGroups,Message message){
        message.setCode(SocketStatus.SOCKET_SUCCESS);
        List<ChannelId> targetChannelIds = targetGroups.stream().map(Member::getChannelId).collect(Collectors.toList());
        for (ChannelId channelId:targetChannelIds) {
            allGroups.find(channelId).writeAndFlush(new TextWebSocketFrame(JSONObject.toJSON(message).toString()));
        }
    }

    public Room getRoom(Integer roomId){
        return rooms.get(roomId);
    }
    public Member getMember(ChannelId channelId){
        return members.get(channelId);
    }
}
